package com.example.financechain.Utils;



import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import org.hyperledger.fabric.protos.ledger.rwset.kvrwset.KvRwset;
import org.hyperledger.fabric.sdk.BlockInfo;
import org.hyperledger.fabric.sdk.Channel;
import org.hyperledger.fabric.sdk.TxReadWriteSetInfo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.apache.http.Consts.UTF_8;
import static org.hyperledger.fabric.sdk.BlockInfo.EnvelopeType.TRANSACTION_ENVELOPE;

@Slf4j
public class ResultCode {


    static String printableString(String string) {
        if (StringUtils.isBlank(string)) {
            return null;
        }
        return string.replaceAll("[^\\p{Print}]", "?");
    }


    Map<String, Long> expectedMoveRCMap = new HashMap<>();
    private static final byte[] EXPECTED_EVENT_DATA = "!".getBytes(UTF_8);
    private static final String EXPECTED_EVENT_NAME = "event";
    private static final Map<String, String> TX_EXPECTED;

    static {
        TX_EXPECTED = new HashMap<>();
        TX_EXPECTED.put("readset1", "Missing readset for channel bar block 1");
        TX_EXPECTED.put("writeset1", "Missing writeset for channel bar block 1");
    }



    //    @Override
    public static HashMap<String,Object> queryFromBlockByTxId(String txid, Channel channel) throws Exception {
        // 获取通道配置
//        if (this.channel == null) {
//            getChannel();
//        }

        /**
         * 通过txid 获取区块信息
         */
       BlockInfo blockInfo = channel.queryBlockByTransactionID(txid);
//        if (blockInfo == null) {
//            return new ResultJson<>(ResultCode.TXID_NOT_EXIST);
//        }

        long blockNumber = blockInfo.getBlockNumber();
        log.info("当前区块编号:{} 数据hash ={}", blockNumber, Hex.encodeHexString(blockInfo.getDataHash()));
        log.info("当前区块编号:{} 前块hash = {}", blockNumber, Hex.encodeHexString(blockInfo.getPreviousHash()));

        // 如果一个通道内有多个链码,就不能通过索引获取了 ---  个人分析未论证
//        BlockInfo.EnvelopeInfo tmp = blockInfo.getEnvelopeInfo(0);
//        String channelId1 = tmp.getChannelId();
//        System.out.println(channelId1);

        Iterable<BlockInfo.EnvelopeInfo> envelopeInfos = blockInfo.getEnvelopeInfos();
        List<String> list = new ArrayList<>();
        HashMap<String,Object> hashMap =new HashMap<>();
        for (BlockInfo.EnvelopeInfo envelopeInfo :envelopeInfos) {
            // 从区块中获取channelId = mychannel
            final String channelId = envelopeInfo.getChannelId();
            log.info("   通道 id: {}", channelId);

            /**
             * 判断不是指定通道名称,则跳过
             */
            if (!channelId.equals(channel.getName())) {
                log.error("通道名称不正确跳过,配置通道id= {},获取的通道id = {}", channel.getName(), channelId);
                continue;
            }

            /**
             * 获取落块时间
             */
            //String time = TimeUtil.parseToyyyyMMddmmssSSS(envelopeInfo.getTimestamp());
            log.info(" 时间: {}", envelopeInfo.getTimestamp());
            hashMap.put("blocktime",envelopeInfo.getTimestamp());

            // 需要定位是组织内的哪个节点
            log.info("  提交事务的身份: {}", envelopeInfo.getCreator().getMspid());
            hashMap.put("identity",envelopeInfo.getCreator().getMspid());
            if (envelopeInfo.getType() != TRANSACTION_ENVELOPE) {
                log.error("envelopeInfo的type值不正确,常量 ={} 解析 ={}", TRANSACTION_ENVELOPE, envelopeInfo.getType());
                continue;
            }
            // 强转类型
            BlockInfo.TransactionEnvelopeInfo transactionEnvelopeInfo = (BlockInfo.TransactionEnvelopeInfo) envelopeInfo;
            log.info("   是否经过校验 {}", transactionEnvelopeInfo.isValid());

            // 获取操作事务的信息
            for (BlockInfo.TransactionEnvelopeInfo.TransactionActionInfo transactionActionInfo : transactionEnvelopeInfo.getTransactionActionInfos()) {

                // 链码名称
                String chaincodeIDName = transactionActionInfo.getChaincodeIDName();
                // 链码版本
                String chaincodeIDVersion = transactionActionInfo.getChaincodeIDVersion();
                log.info("  proposal chaincodeIDName:{}, chaincodeIDVersion: {}", chaincodeIDName, chaincodeIDVersion);

                // 操作事务的读写集
                TxReadWriteSetInfo rwsetInfo = transactionActionInfo.getTxReadWriteSet();

                if (null != rwsetInfo) {
                    //我只要了写集合的数据
                    for (TxReadWriteSetInfo.NsRwsetInfo nsRwsetInfo : rwsetInfo.getNsRwsetInfos()) {
                        // 含有默认链码 _lifecycle  和 自定义链码
                        String namespace = nsRwsetInfo.getNamespace();
                        // 只要符合要求的链码的
                        if (namespace.equals("_lifecycle")) {
                            log.error("链码名称不正确 跳过 ,namespace ={} fabricConfig.getChainCodeName() ={}", namespace, "sacc");
                            continue;
                        }
                        KvRwset.KVRWSet rws = nsRwsetInfo.getRwset();
                        for (KvRwset.KVWrite writeList : rws.getWritesList()) {
                            String valAsString = printableString(new String(writeList.getValue().toByteArray(), UTF_8));
                            //log.info("Namespace {}  key {} has value '{}' ", namespace, writeList.getKey(), valAsString);
                            String key = writeList.getKey().toString();
                            String value = writeList.getValue().toStringUtf8(); // 将字节数据转换为UTF-8编码字符串
                            //System.out.println("Key: " + key + ", Value: " + value);
                            if (StringUtils.isNotBlank(value)) {
                                list.add(value);
                            }


                        }

                    }
                }
            }
        }
        hashMap.put("blockInfo",list);
        return hashMap;
      //  return new ResultJson<List<JSONObject>>(ResultCode.OK, list);
    }

}
